package club.hicode.daydayup.protostuff;

import io.protostuff.LinkedBuffer;
import io.protostuff.ProtobufIOUtil;
import io.protostuff.Schema;
import io.protostuff.runtime.RuntimeSchema;

/**
 * ProtostuffUtil 工具库,封装了操作 Protobuf 的操作<br>
 * protostuff是一个基于protobuf实现的序列化方法，它较于protobuf最明显的好处是，在几乎不损耗性能的情况下做到了不用我们写.proto文件来实现序列化
 *
 * @author Liu Chunfu
 * @date 2018-05-02 下午2:56
 **/
public class ProtostuffUtil {

    private ProtostuffUtil() {
    }

    /**
     * 将指定对象序列化
     *
     * @param obj 具体对象
     * @param <T> 具体对象的 class
     * @return 序列化后的 byte 数组
     */
    public static <T> byte[] serializer(T obj) {
        LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
        try {
            Schema<T> schema = RuntimeSchema.createFrom((Class<T>) obj.getClass());
            return ProtobufIOUtil.toByteArray(obj, schema, buffer);
        } catch (Exception e) {
            throw new IllegalArgumentException(e);
        } finally {
            buffer.clear();
        }
    }

    /**
     * 将二进制的数组转换为实体类对象
     *
     * @param bytes 二进制字节数组
     * @param clazz 目标类类型
     * @param <T>   目标类类型的泛型
     * @return
     */
    public static <T> T deserializer(byte[] bytes, Class<T> clazz) {
        try {
            //获取类的描述架构
            Schema schema = RuntimeSchema.getSchema(clazz);
            //创建结果类
            Object obj = schema.newMessage();
            //将结果类将内容补充完成。
            ProtobufIOUtil.mergeFrom(bytes, obj, schema);
            return (T) obj;
        } catch (Exception e) {
            throw new IllegalArgumentException(e);
        }
    }
}
